﻿using System;
using System.Collections.Generic;
using System.Transactions;

namespace Kaesoft.Hospedaje.Business
{
    /// <summary>
    /// Centraliza el manejo de transacciones
    /// </summary>
    public static class TransactionHelper
    {
        #region Campos Privados
        private static Dictionary<Guid, CommittableTransaction> _currentTransactions
            = new Dictionary<Guid, CommittableTransaction>();
        #endregion

        #region Metodos Publicos
        /// <summary>
        /// Crea una nueva transacción
        /// </summary>
        /// <returns>Token único que identifica a la transacción</returns>
        public static Guid CreateTransaction()
        {
            Guid newToken = Guid.NewGuid();

            TransactionOptions txop = new TransactionOptions
                                          {
                                              IsolationLevel = IsolationLevel.ReadCommitted,
                                              Timeout = new TimeSpan(0, 0, 30)
                                          };
            CommittableTransaction transaction = new CommittableTransaction(txop);

            _currentTransactions.Add(newToken, transaction);
            Transaction.Current = transaction;

            return newToken;
        }

        /// <summary>
        /// Setea la transaccion actual
        /// </summary>
        /// <param name="transactionToken">Identificador de la transaccion</param>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
        public static void SetCurrentTransaction(Guid transactionToken)
        {
            if (!_currentTransactions.ContainsKey(transactionToken)) throw new KeyNotFoundException("No transaction exists for the given token.");
            Transaction.Current = _currentTransactions[transactionToken];
        }

        /// <summary>
        /// Ejecuta Commit para la transacción actual y la elimina de las activas
        /// </summary>
        /// <param name="transactionToken">El identificador de la transacción</param>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference", MessageId = "0#")]
        public static void CommitTransaction(ref Guid transactionToken)
        {
            if (!_currentTransactions.ContainsKey(transactionToken)) throw new InvalidOperationException("No transaction exists for the given token.");
            //commit 
            _currentTransactions[transactionToken].Commit();
            _currentTransactions.Remove(transactionToken);
            transactionToken = Guid.Empty;
            Transaction.Current = null;
        }

        /// <summary>
        /// Ejecuta Rollback de la transacción
        /// </summary>
        /// <param name="transactionToken">El identificador de la transacción</param>
        public static void RollbackTransaction(Guid transactionToken)
        {
            if (!_currentTransactions.ContainsKey(transactionToken)) throw new InvalidOperationException("No transaction exists for the given token.");
            //rollback
            _currentTransactions[transactionToken].Rollback();
            _currentTransactions.Remove(transactionToken);
            Transaction.Current = null;
        }
        #endregion
    }
}